package moe.feng.common.stepperview;

import ohos.agp.components.*;
import ohos.agp.components.element.Element;
import ohos.agp.utils.Color;
import ohos.app.Context;

import java.util.Collections;

public class VerticalStepperView extends StackLayout implements IStepperView {
    /**
     * Internal view / adapter
     */
    private ListContainer mListView;
    private ItemAdapter mAdapter;

    /**
     * View State
     */
    private IStepperAdapter mStepperAdapter;
    private int mCurrentStep = 0;
    private String[] mErrorTexts = null;

    /**
     * View attributes
     */
    private boolean mAnimationEnabled;
    private int mAnimationDuration;
    private int mNormalColor;
    private int mActivatedColor;
    private int mLineColor;
    private int mErrorColor;
    private Element mDoneIcon;
    private boolean mAlwaysShowSummary = false;

    public VerticalStepperView(Context context) {
        this(context, null);
    }

    public VerticalStepperView(Context context, AttrSet attrs) {
        this(context, attrs, "");
    }

    public VerticalStepperView(Context context, AttrSet attrs, String defStyleAttr) {
        super(context, attrs, defStyleAttr);
        initColor();
        prepareListView(context);
        if (attrs != null) {
            mNormalColor = TypedAttrUtils.getIntColor(attrs, "step_normal_color", mNormalColor);
            mActivatedColor = TypedAttrUtils.getIntColor(attrs, "step_activated_color", mActivatedColor);
            mAnimationDuration = TypedAttrUtils.getInteger(attrs, "step_animation_duration", mAnimationDuration);
            mAnimationEnabled = TypedAttrUtils.getBoolean(attrs, "step_enable_animation", true);
            mLineColor = TypedAttrUtils.getIntColor(attrs, "VerticalStepperView_step_line_color", mLineColor);
            mErrorColor = TypedAttrUtils.getIntColor(attrs, "step_error_highlight_color", mErrorColor);
            mAlwaysShowSummary = TypedAttrUtils.getBoolean(attrs, "step_show_summary_always", mAlwaysShowSummary);
            if (null != TypedAttrUtils.getElement(attrs, "step_done_icon", null)) {
                mDoneIcon = TypedAttrUtils.getElement(attrs, "step_done_icon", null);
            }
        }
        setAnimationEnabled(mAnimationEnabled);
    }

    private void initColor() {
        mNormalColor = Color.getIntColor("#9E9E9E");
        mActivatedColor = Color.getIntColor("#2196F3");
        mLineColor = Color.getIntColor("#9E9E9E");
        mErrorColor = Color.getIntColor("#F44336");
    }

    private void prepareListView(Context context) {
        mListView = new ListContainer(context);
        mAdapter = new ItemAdapter(context);
        mListView.setClipEnabled(false);
        mListView.setPadding(0, 24, 0, 0);
        mListView.setLayoutManager(new DirectionalLayoutManager());
        mListView.setItemProvider(mAdapter);
        addComponent(mListView, new ComponentContainer.LayoutConfig(ComponentContainer.LayoutConfig.MATCH_PARENT, ComponentContainer.LayoutConfig.MATCH_PARENT));
    }

    public void setStepperAdapter(IStepperAdapter stepperAdapter,Context context) {
        mStepperAdapter = stepperAdapter;
        mListView.setItemProvider(null);
        mAdapter = new ItemAdapter(context);
        mListView.setItemProvider(mAdapter);
        updateSteppers();
    }

    public void updateSteppers() {
        if (mErrorTexts == null || mErrorTexts.length != mStepperAdapter.size()) {
            mErrorTexts = new String[mStepperAdapter.size()];
        }
        mAdapter.notifyDataChanged();
    }

    public void setAlwaysShowSummary(boolean alwaysShowSummary) {
        mAlwaysShowSummary = alwaysShowSummary;
        updateSteppers();
    }

    /**
     * Should show summary always
     *
     * @return If should show summary always
     */
    @Override
    public boolean isAlwaysShowSummary() {
        return mAlwaysShowSummary;
    }

    public void setErrorText(int index, String errorText) {
        if (mErrorTexts == null) {
            mErrorTexts = new String[mStepperAdapter.size()];
        }
        mErrorTexts[index] = errorText;
        updateSteppers();
    }

    /**
     * Get error text of item
     *
     * @param index Index
     * @return Error text or null (means no error)
     */
    public String getErrorText(int index) {
        if (mErrorTexts != null) {
            return mErrorTexts[index];
        }
        return null;
    }

    /**
     * Return the count of steps
     *
     * @return The count of steps
     */
    public int getStepCount() {
        return mStepperAdapter != null ? mStepperAdapter.size() : 0;
    }

    /**
     * Return if stepper can go next
     *
     * @return If stepper can go next
     */
    public boolean canNext() {
        return mStepperAdapter != null && mCurrentStep < mStepperAdapter.size() - 1;
    }

    /**
     * Return if stepper can go previous
     *
     * @return If stepper can go previous
     */
    public boolean canPrev() {
        return mStepperAdapter != null && mCurrentStep > 0;
    }

    /**
     * Go next step
     *
     * @return If success
     */
    public boolean nextStep() {
        if (canNext()) {
            mStepperAdapter.onHide(mCurrentStep);
            mCurrentStep++;
            mStepperAdapter.onShow(mCurrentStep);
            if (mAnimationEnabled) {
                mAdapter.notifyDataSetItemRangeChanged(mCurrentStep - 1, 2);
            } else {
                mAdapter.notifyDataChanged();
            }
            return true;
        }
        return false;
    }

    /**
     * Go previous step
     *
     * @return If success
     */
    public boolean prevStep() {
        if (canPrev()) {
            mStepperAdapter.onHide(mCurrentStep);
            mCurrentStep--;
            mStepperAdapter.onShow(mCurrentStep);
            if (mAnimationEnabled) {
                mAdapter.notifyDataSetItemRangeChanged(mCurrentStep, 2);
            } else {
                mAdapter.notifyDataChanged();
            }
            return true;
        }
        return false;
    }

    /**
     * Get Stepper Adapter
     *
     * @return Stepper Adapter
     */
    @Override
    public IStepperAdapter getStepperAdapter() {
        return mStepperAdapter;
    }

    /**
     * Get the index of current step
     *
     * @return The index of current step
     */
    @Override
    public int getCurrentStep() {
        return mCurrentStep;
    }

    public void setNormalColor(int color) {
        mNormalColor = color;
        mAdapter.notifyDataChanged();
    }

    /**
     * Get normal point color
     *
     * @return Normal Point Color
     */
    @Override
    public int getNormalColor() {
        return mNormalColor;
    }

    public void setActivatedColor(int color) {
        mActivatedColor = color;
        mAdapter.notifyDataChanged();
    }

    /**
     * Get activated point color
     *
     * @return Activated Point Color
     */
    @Override
    public int getActivatedColor() {
        return mActivatedColor;
    }

    public void setErrorColor(int color) {
        mErrorColor = color;
        mAdapter.notifyDataChanged();
    }

    /**
     * Get error highlight color
     *
     * @return Error Highlight Color
     */
    @Override
    public int getErrorColor() {
        return mErrorColor;
    }

    public void setLineColor(int color) {
        mLineColor = color;
        mAdapter.notifyDataChanged();
    }

    /**
     * Get Line color
     *
     * @return Line Color
     */
    @Override
    public int getLineColor() {
        return mLineColor;
    }

    /**
     * Get animation duration
     *
     * @return Animation duration
     */
    @Override
    public int getAnimationDuration() {
        return mAnimationDuration;
    }

    /**
     * Get done icon drawable
     *
     * @return Done Icon Drawable
     */
    @Override
    public Element getDoneIcon() {
        return mDoneIcon;
    }

    public void setAnimationEnabled(boolean enabled) {
        mAnimationEnabled = enabled;
    }

    /**
     * Return if animation is enabled
     *
     * @return If animation is enabled
     */
    public boolean isAnimationEnabled() {
        return mAnimationEnabled;
    }

    public void setCurrentStep(int currentStep) {
        int minIndex = Math.min(currentStep, mCurrentStep);
        int count = Math.abs(mCurrentStep - currentStep) + 1;

        mCurrentStep = currentStep;
        if (mAnimationEnabled) {
            mAdapter.notifyDataSetItemRangeChanged(minIndex, count);
        } else {
            mAdapter.notifyDataChanged();
        }
    }

    class ItemAdapter extends BaseItemProvider {
        private Context context;

        ItemAdapter(Context context) {
            this.context = context;
        }

        @Override
        public int getCount() {
            return getStepCount();
        }

        @Override
        public Object getItem(int i) {
            return Collections.emptyList();
        }

        @Override
        public long getItemId(int i) {
            return 0;
        }

        @Override
        public Component getComponent(int position, Component component, ComponentContainer componentContainer) {
            component = new VerticalStepperItemView(context, 0);
            ItemHolder holder = new ItemHolder((VerticalStepperItemView) component);
            holder.mItemView.setIndex(position + 1);
            holder.mItemView.setIsLastStep(position == getCount() - 1);
            holder.mItemView.setTitle(getStepperAdapter().getTitle(position));
            holder.mItemView.setSummaryFinished(getStepperAdapter().getSummary(position));
            holder.mItemView.setSummary(getStepperAdapter().getSummary(position));
            holder.mItemView.setNormalColor(mNormalColor);
            holder.mItemView.setActivatedColor(mActivatedColor);
            holder.mItemView.setAnimationDuration(mAnimationDuration);
            holder.mItemView.setDoneIcon(mDoneIcon);
            holder.mItemView.setAnimationEnabled(mAnimationEnabled);
            holder.mItemView.setLineColor(mLineColor, 1);
            holder.mItemView.setErrorColor(mErrorColor);
            holder.mItemView.setErrorText(mErrorTexts[position]);
            holder.mItemView.setAlwaysShowSummary(mAlwaysShowSummary);
            if (getCurrentStep() > position) {
                holder.mItemView.setState(VerticalStepperItemView.STATE_DONE, position, 1);
            } else if (getCurrentStep() < position) {
                holder.mItemView.setState(VerticalStepperItemView.STATE_NORMAL, position, 1);
            } else {
                holder.mItemView.setState(VerticalStepperItemView.STATE_SELECTED, position, 1);
            }
            holder.mItemView.removeCustomView();
            Component customView = getStepperAdapter().onCreateCustomView(position, getContext(), holder.mItemView);
            if (customView != null) {
                holder.mItemView.addCustomViewComponet(customView);
            }
            return component;
        }

        class ItemHolder {
            VerticalStepperItemView mItemView;

            ItemHolder(VerticalStepperItemView itemView) {
                mItemView = itemView;
                ComponentContainer.LayoutConfig layoutConfig = new ComponentContainer.LayoutConfig(ComponentContainer.LayoutConfig.MATCH_PARENT, ComponentContainer.LayoutConfig.MATCH_CONTENT);
                mItemView.setLayoutConfig(layoutConfig);
            }
        }
    }

}
